package core.process;

import core.wm.WM;
import core.process.pack.MatchPack;
import core.utils.EPara;
import core.rb.MB;
import core.rb.IB;
import core.rb.r.IR;
import core.rb.r.MR;
import core.sb.s.Seq;
import gui.processor.Processor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.concurrent.CountDownLatch;

/*Author: John Archer, Contact: john.archer.jpa@gmail.com*/
public class Match{
    private IB ib;
    private HashMap <String, LinkedList <Integer>>  T_HASH_MAP;
    private Processor gp;
    public Match(IB ib, Processor gp){
        this.ib = ib;
        this.gp = gp;
        T_HASH_MAP = setUpHash(this.ib.getRef());
    }
    private HashMap <String, LinkedList <Integer>> setUpHash(Seq ref){
        HashMap <String, LinkedList <Integer>> hash = new HashMap <String, LinkedList <Integer>>();
        int noOfWords = ref.getDNA().length() - (EPara.KMER_LEN - 1);
        String word;
        for (int loc = 0; loc < noOfWords; loc++) {
            word = ref.getDNA().substring(loc, loc + EPara.KMER_LEN);
            if(hash.containsKey(word)){hash.get(word).add(loc);}
            else{
                LinkedList <Integer> i = new LinkedList();
                i.add(new Integer(loc));
                hash.put(word, i);
            }
        }
        return hash;
    }
    public MB getMB() throws Exception{
        int size = (ib.getSize() / EPara.THREADS);
        int i = 0;
        ArrayList <IB> packs = new ArrayList();
        ArrayList <IR> pack;
        for(int x = 0; x<EPara.THREADS; x++){
            pack = new ArrayList();
            for(int y = 0; y<size; y++){pack.add(ib.getRead(i++));}
            packs.add(new IB(ib.getRef(), pack));
        }
        IB fPack = packs.get(0);
        for(int x=i; x<ib.getSize(); x++){fPack.add(ib.getRead(i++));}
        MatchPack [] mp = new MatchPack[packs.size()];
        CountDownLatch cdl = new CountDownLatch(packs.size());
        for (int x = 0; x < packs.size(); x++) {
            if(x==0){mp[x] = new MatchPack(gp, cdl, packs.get(x), new WM(ib.getRef().getDNA(), T_HASH_MAP, EPara.KMER_LEN, EPara.KMER_DENS));}
            else{mp[x] = new MatchPack(null, cdl, packs.get(x), new WM(ib.getRef().getDNA(), T_HASH_MAP, EPara.KMER_LEN, EPara.KMER_DENS));}
        }
        cdl.await();

        ArrayList <MR> [] comb = new ArrayList[ib.getRef().getDNA().length()];
        for(int s=0; s<comb.length; s++){comb[s] = new ArrayList <MR> ();}

        ArrayList <MR> [] packReads;
        for (int p = 0; p < mp.length; p++) {
            packReads = mp[p].getPOut();
            for(int s=0; s<packReads.length; s++){
                for(int r=0; r<packReads[s].size(); r++){comb[s].add(packReads[s].get(r));}
            }
        }
        MB mb = new MB(ib.getRef());
        for(int s=0; s<comb.length; s++){
            for(int r=0; r<comb[s].size(); r++){mb.add(comb[s].get(r));}
        }
        return mb;
    }
}